#include "disp.h" /* include your own disp.h file (e.g. hw1)*/

/* Camera defaults */
#define	DEFAULT_FOV		35.0
#define	DEFAULT_IM_Z	(-10.0)  /* world coords for image plane origin */
#define	DEFAULT_IM_Y	(5.0)    /* default look-at point = 0,0,0 */
#define	DEFAULT_IM_X	(-10.0)

#define	DEFAULT_AMBIENT		{0.1, 0.1, 0.1}
#define	DEFAULT_DIFFUSE		{0.7, 0.6, 0.5}
#define	DEFAULT_SPECULAR	{0.2, 0.3, 0.4}
#define	DEFAULT_SPEC		32

#define	MATLEVELS	100		/* how many matrix pushes allowed *///
#define	MAX_LIGHTS	10		/* how many lights allowed */

#define L 0		/*the location of the edge of the tri*/
#define R 1
#define T 2
#define B 3

#define PI 3.14159265

/* Dummy definition : change it later */
/*#ifndef GzLight
#define GzLight		GzPointer
#endif
*/
/*#ifndef GzTexture
#define GzTexture	GzPointer
#endif*/

#ifndef GZRENDER
#define GZRENDER
typedef struct {			/* define a renderer */
	GzRenderClass	renderClass;
	GzDisplay		*display;
	short		    open;
	GzCamera		camera;
	short		    matlevel;	        /* top of stack - current xform */
	GzMatrix		Ximage[MATLEVELS];	/* stack of xforms (Xsm) */
	GzMatrix		Xnorm[MATLEVELS];	/* xforms for norms (Xim) */
	GzMatrix		Xsp;		        /* NDC to screen (pers-to-screen) */
	GzColor			flatcolor;          /* color state for flat shaded triangles */
	int				interp_mode;
	int				numlights;
	GzLight			lights[MAX_LIGHTS];
	GzLight			ambientlight;
	GzColor			Ka, Kd, Ks;
	float		    spec;		/* specular power */
	GzTexture		tex_fun;    /* tex_fun(float u, float v, GzColor color) */
} GzRender;
#endif

#ifndef EDGEDDA
#define EDGEDDA
typedef struct {		/*define an edge DDA*/
	GzCoord		vStart;
	GzCoord		vEnd;
	GzCoord		vCurrent;
	float		slopex;
	float		slopez;
	int			lr;		/*the location of the edge*/
} EdgeDDA;
#endif

#ifndef SPANDDA
#define SPANDDA			/*define a span DDA*/
typedef struct {
	float xStart;
	float zStart;
	float xEnd;
	float zEnd;
	float xCurrent;
	float zCurrent;
	float slopez;
} SpanDDA;
#endif

// Function declaration
// HW2
int GzNewRender(GzRender **render, GzRenderClass renderClass, GzDisplay *display);
int GzFreeRender(GzRender *render);
int GzBeginRender(GzRender	*render);
int GzPutAttribute(GzRender	*render, int numAttributes, GzToken	*nameList, GzPointer *valueList);
int GzPutTriangle(GzRender *render, int	numParts, GzToken *nameList, GzPointer *valueList);
short ctoi(float color);
void YSort(EdgeDDA *e1,EdgeDDA *e2,EdgeDDA *e3,GzCoord *vertex,GzCoord *normal,GzTextureIndex *uv,GzColor *color);
void InitEdgeDDA(EdgeDDA *e,float *v1,float *v2);
void InitEdgeDDAT(EdgeDDA *e,float *v1,float *v2);
void InitEdgeDDAB(EdgeDDA *e,float *v1,float *v2);
void LRTest(EdgeDDA *e1,EdgeDDA *e2,EdgeDDA *e3);
void InitSpanDDA(SpanDDA *s,EdgeDDA *e1,EdgeDDA *e2);
void AdvanceYCeiling(EdgeDDA *e);
void MatrixMultiply (float (*a)[4], float (*b)[4], float (*c)[4]);
void MatrixVectorMultiply (float (*a)[4], float (*b)[1], float (*c)[1]);
void CopyMatrix(float (*target)[4],float (*source)[4]);

// HW3
int GzPutCamera(GzRender *render, GzCamera *camera);
int GzPushMatrix(GzRender *render, GzMatrix	matrix);
int GzPopMatrix(GzRender *render);

//HW4
int Unitary(GzMatrix matrix);
void GouraudInterpolation(GzRender *render,GzColor *color,GzCoord *vertex,GzCoord *normal,short &red,short &green,short &blue,float x,float y,float z);
void PhongInterpolation(GzRender *render,GzCoord *vertex,GzCoord *normal,short &red,short &green,short &blue,float x,float y,float z);
double ZInterpolation(GzCoord *vertex,float x,float y);
void ComputeColor(GzRender *render,int numverts,GzCoord *normal,GzColor *color);
float VectorLength(GzCoord a);
float DotProduct(GzCoord a,GzCoord b);
void CrossProduct(GzCoord a,GzCoord b,GzCoord result);
void shade(GzCoord norm, GzCoord color);
void Rasterization(GzRender *render,GzCoord *vertex,GzCoord *normal,GzTextureIndex *uv,GzColor *color,EdgeDDA *e1,EdgeDDA *e2,int interpMode);

//HW5
float CalcZv(float Zs);
float Wrap(float P,float Zs);
float UnWrap(float Ps,float Zs);
void UVInterpolation(GzCoord *vertex,GzTextureIndex *uv,float &u,float &v,float x,float y);
void GetTextureColor(GzTextureIndex *uv,GzColor color,GzCoord *vertex,float x,float y,float z,GzTexture tex);

//TEX_FUN
int tex_fun(float u, float v, GzColor color);

// Object Translation
int GzRotXMat(float degree, GzMatrix mat);
int GzRotYMat(float degree, GzMatrix mat);
int GzRotZMat(float degree, GzMatrix mat);
int GzTrxMat(GzCoord translate, GzMatrix mat);
int GzScaleMat(GzCoord scale, GzMatrix mat);
